package me.leon.ade

import java.io.FileInputStream
import java.net.HttpURLConnection
import java.net.URLDecoder
import java.security.DigestInputStream
import java.security.MessageDigest
import java.util.regex.Pattern
import kotlin.math.ceil

object NetHelper {

    private val REG_CONTENT_DISPOSITION =
        Pattern.compile("filename=([^;]*)$|filename\\*=\"?.*'+([^;'\"]+)\"?")
    const val ILLEGAL_FILE_NAME_PATTERN = "[\\/:?*\"<>|]"
    private val REG_CHINESE = Pattern.compile("[\\u4e00-\\u9fa5]")

    const val COMMON_UA =
        "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 " +
            "(KHTML, like Gecko) Chrome/86.0.4240.198 Mobile Safari/537.36"

    /** 根据响应头或者url获取文件名 */
    fun getNetFileName(response: HttpURLConnection, url: String) =
        getCorrectUrl(
            URLDecoder.decode(
                response.getHeaderField("Content-Disposition").also { println(response) }?.let {
                    getFileName(it)
                }
                    ?: response.getHeaderField("content-disposition")?.let { getFileName(it) }
                        ?: getUrlFileName(url).also { println("getUrlFileName $it") }
                        ?: "unknownfile_${System.currentTimeMillis()}"
            )
        )

    private fun getCorrectUrl(url: String) =
        url.toByteArray(Charsets.ISO_8859_1).toString(Charsets.UTF_8).takeIf {
            REG_CHINESE.matcher(it).find()
        }
            ?: url

    /**
     * 通过 ‘？’ 和 ‘/’ 判断文件名
     * http://mavin-manzhan.oss-cn-hangzhou.aliyuncs.com/1486631099150286149.jpg?x-oss-process=image/watermark,image_d2F0ZXJtYXJrXzIwMF81MC5wbmc
     */
    private fun getUrlFileName(url: String): String? {
        var filename: String? = null
        val strings = url.split("/").toTypedArray()
        for (string in strings) {
            if (string.contains("?")) {
                val endIndex = string.indexOf('?')
                if (endIndex != -1) {
                    filename = string.substring(0, endIndex)
                    return filename
                }
            }
        }
        if (strings.isNotEmpty()) {
            filename = strings[strings.size - 1]
        }
        return filename
    }

    fun getFileName(dispositionHeader: String): String? {
        val matcher = REG_CONTENT_DISPOSITION.matcher(dispositionHeader)
        if (matcher.find()) {
            for (i in 1..2) {
                if (!matcher.group(i).isNullOrEmpty()) {
                    return matcher.group(i)
                }
            }
        }
        return null
    }
}

fun Long.slice(group: Int, minSize: Long = 1024 * 1024): MutableList<LongRange> {

    val blockSize = (this / group).takeIf { this >= group * minSize } ?: minSize
    val gp = group.takeIf { this >= group * minSize } ?: ceil(this / minSize.toDouble()).toInt()

    val tList = ArrayList<LongRange>()
    for (i in 0 until gp) {
        tList.add(
            (blockSize * i until blockSize * (i + 1)).takeIf { i != gp - 1 }
                ?: (blockSize * i until this)
        )
    }
    return tList
}

fun <T> Any?.safeAs(): T? = this as? T

fun String.fileMd5(): String {
    val md5Digest = MessageDigest.getInstance("MD5")
    DigestInputStream(FileInputStream(this), md5Digest).use {
        while (it.read(ByteArray(1024 * 1024)) > 0) ;
        return md5Digest.digest().toHexString().uppercase()
    }
}

fun ByteArray.toHexString() =
    this.fold(StringBuilder()) { acc, byte ->
            val hv = Integer.toHexString(byte.toInt() and 0xFF)
            if (hv.length < 2) acc.append(0)
            acc.append(hv)
        }
        .toString()

fun Long.speed(): String =
    when (this) {
        in 0L until 1024L -> "$this B/s"
        in 1024L until 1048576L -> "${this / 1024} KB/s"
        in 1048576L until 1073741824L -> "${this / 1048576} MB/s"
        else -> "${this / 1073741824L} GB/s"
    }
